package de.fmaul.dicheck.reporting;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import de.fmaul.dicheck.model.Property;
import de.fmaul.dicheck.model.TestCase;
import de.fmaul.dicheck.model.TestContainer;
import de.fmaul.dicheck.runner.TestResult;
import de.fmaul.dicheck.runner.TestRunnerResult;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateModelException;

/**
 * @author florian
 * 
 */
public class FreemarkerReportProvider implements ReportProvider {
    private static Logger log = Logger
            .getLogger(FreemarkerReportProvider.class);

    private final String outputDir;
    private final Configuration freemarkerConfig;

    public FreemarkerReportProvider(final String templateDir,
            final String outputDir) {

        this.outputDir = outputDir;

        log.info(outputDir);

        freemarkerConfig = new Configuration();
        try {

            freemarkerConfig.setDirectoryForTemplateLoading(new File(
                    templateDir));
            freemarkerConfig.setObjectWrapper(new DefaultObjectWrapper());
        } catch (final IOException e) {
            log.error("Error creating freemarker configuration.", e);
        }
    }

    public File generateReport(final TestContainer testSuite,
            final TestRunnerResult testResults, Statistics stats) {
        final File reportdir = new File(outputDir);

        if (!reportdir.exists()) {
            reportdir.mkdirs();
        }

        // TODO NameGenStrategy
        final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        final String filename = "report_" + sdf.format(new Date()) + ".html";

        final File reportfile = new File(reportdir.getAbsolutePath()
                + File.separator + filename);

        createReport(testSuite, testResults, stats, reportfile);
        
        return reportfile;
    }



    private void createReport(final TestContainer testSuite,
            final TestRunnerResult runnerResult, final Statistics stats, final File reportfile) {

        class LookupResultMethod implements TemplateMethodModel {

            @SuppressWarnings("unchecked")
            public Object exec(final List args) throws TemplateModelException {
                if (args.size() != 1) {
                    throw new TemplateModelException("Wrong arguments");
                }
                final String testId = (String) args.get(0);
                return runnerResult.getTestResultByTestId(testId);
            }
        }

        class LookupTotalsMethod implements TemplateMethodModel {
            @SuppressWarnings("unchecked")
            public Object exec(final List args) throws TemplateModelException {
                if (args.size() != 1) {
                    throw new TemplateModelException("Wrong arguments");
                }

                final String containerId = (String) args.get(0);
                final Object o = stats.getTotals(containerId);
                return o;
            }
        }

        try {
            String template = testSuite.getProperties().getProperty(
                    Property.REPORT_TEMPLATE, "report.ftl");

            final Template temp = freemarkerConfig.getTemplate(template);
            
            final Map<String, Object> root = new HashMap<String, Object>();
            root.put("suite", testSuite);
            root.put("lookupResult", new LookupResultMethod());
            root.put("lookupTotals", new LookupTotalsMethod());

            final Writer fileout = new FileWriter(reportfile);
            try {
                temp.process(root, fileout);
            } catch (final TemplateException e) {
                log
                        .error(
                                "Error processing freemarker template for report generation.",
                                e);
            }
            fileout.close();
        } catch (final IOException e) {
            log.error("Error writing report file.", e);
        }
    }

}
